package shaw.wifi.nohttp;

import java.io.IOException;

import shaw.wifi.Constants;
import shaw.wifi.NetworkSettingsTaskManager;
import shaw.wifi.network.ConnectionInformation;
import shaw.wifi.network.NetworkSettings;
import android.content.Context;
import android.net.wifi.WifiManager;
import android.util.Log;

public class NetworkSettingsAESTask extends NetworkSettingsNoHttpTask {
	private ConnectionInformation connInfo;
	private NetworkSettings networkSettings = new NetworkSettings();
	
	@Override
	protected Integer doInBackground(ConnectionInformation... params) {
		if(params.length != 1) {
			publishProgress("Invalid parameters...");
			return null;
		}
		connInfo = params[0];
		
		if(!setupSocketConnection()) {
			NetworkSettingsTaskManager.get().clearTasks();
			return null;
		}
		
		boolean update = getNetworkSettings();
		
		if(update) {
			updateNetworkSettings();
		}
		
		Constants._FINISHED = true;
		
		closeConnection();
		
		return null;
	}
	
	private void closeConnection() {
		
		try {
			connInfo.ois.close();
			connInfo.oos.close();
			connInfo.socket.close();
			connInfo.socket = null;
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	
	private boolean updateNetworkSettings() {
		if(this.isCancelled() == true) {
			return false;
		}
		interruptable = false;
		
		WifiManager wifi = (WifiManager) NetworkSettingsTaskManager.get().getApplicationContext().getSystemService(Context.WIFI_SERVICE);
		boolean disableOpen = connInfo.disableShawOpen;
		
		//apply the network settings, and check if the application was successful
		networkSettings.setType(NetworkSettings.WIFI_PEAP);
    	boolean r = networkSettings.apply(wifi, disableOpen);
    	if(r == true) {
    		//settings applied successfully, inform user
    		publishProgress("\nUpdated settings successfully");
    	} else {
    		//apply settings failed, inform user
    		publishProgress("\nFailed to update settings");
    	}
    	
		return r;
	}
	
	private boolean getNetworkSettings() {
		//we have the PSK setup from before, we want to encrypt the shared key we are going to use to transmit the network info,
		//as well as our user identification
		ShawWifiMessage msg = new ShawWifiMessage(3);
		msg.type = ShawWifiMessage.TYPE_NETWORKSETTINGS;
		msg.header[0] = "action";
		msg.data[0] = "getpeap".getBytes();
		msg.header[1] = "username";
		msg.data[1] = connInfo.username.getBytes();
		msg.header[2] = "password";
		msg.data[2] = connInfo.password.getBytes();
		if(!sendCryptMessage(msg)) {
			return false; //cannot send message, error in sendMessage() method
		}
		
		publishProgress("Send getpeap message");
		
		//wait for server response
		ShawWifiMessage response = waitForCryptMessage();
		if(response == null) {
			return false;
		}
		
		String ssid = null;
		String oldSsid = null;
		String peap_user = null;
		String peap_pass = null;
		
		try{
			//should be an Network settings message
			for(int i = 0; i<response.header.length; i++) {
				Log.e("AEST", response.header[i] + " : " + new String(response.data[i]));
			}
			if(response.type != ShawWifiMessage.TYPE_NETWORKSETTINGS) throw new UnexpectedMessageException("expected network settings message " + response.type);
			
			//we want either 1 header (login = fail) or 5 headers (login = true, ssid, old ssid, peap user, peap passwd)
			if(response.length != 1 && response.length != 5) throw new UnexpectedMessageException("expected 1 or 5 headers");
			
			//get the useful information from the headers
			if(response.length == 1) {
				if(!response.header[0].equals("LOGIN")) throw new UnexpectedMessageException("expected header LOGIN " + response.header[0]);
				publishProgress("Invalid app credentials, try reinstalling the application");
				return false;
			} else {
				//check for anticiapted headers
				if(!response.header[0].equals("LOGIN")) throw new UnexpectedMessageException("expected header LOGIN " + response.header[0]);
				if(!response.header[1].equals("NETWORK")) throw new UnexpectedMessageException("expected header NETWORK " + response.header[1]);
				if(!response.header[2].equals("OPENNETWORK")) throw new UnexpectedMessageException("expected header OPENNETWORK " + response.header[2]);
				if(!response.header[3].equals("USERNAME")) throw new UnexpectedMessageException("expected header USERNAME " + response.header[3]);
				if(!response.header[4].equals("PASSWORD")) throw new UnexpectedMessageException("expected header PASSWORD " + response.header[4]);
				
				//suggested values response
				Log.e("GOT RESPONSE", "length is " + response.data[1].length);
				if(!(new String(response.data[0]).equals("true"))) {
					publishProgress("Invalid app credentials, try reinstalling the application");
					return false;
				}
				ssid = new String(response.data[1]);
				Constants._OPENSSID = oldSsid = new String(response.data[2]);
				peap_user = new String(response.data[3]);
				peap_pass = new String(response.data[4]);
				networkSettings.setSSID(ssid);
				Constants._OPENSSID = oldSsid;
				networkSettings.setPeapUser(peap_user);
				networkSettings.setPeapPass(peap_pass);
				
				if(Constants._SHOWSTUFF) {
					publishProgress("Got values for network " + ssid);
					publishProgress(">>open network " + oldSsid);
					publishProgress(">>peap username " + peap_user);
					publishProgress(">>peap password " + peap_pass);
				}
			}
			
		} catch(UnexpectedMessageException e) {
			e.printStackTrace();
			publishProgress("Received unexpected message from server, please make sure you have the most recent version of the application");
			return false;
		}
		
		//send a message which requests the username and password to be set to these values
		msg = new ShawWifiMessage(3);
		msg.type = ShawWifiMessage.TYPE_NETWORKSETTINGS;
		msg.header[0] = "action"; msg.data[0] = "setpeap".getBytes();
		msg.header[1] = "crad_user";
		msg.data[1] = peap_user.getBytes();
		msg.header[2] = "crad_pass";
		msg.data[2] = peap_pass.getBytes();
		if(!sendCryptMessage(msg)) {
			return false; //cannot send message, error in sendMessage() method
		}
		
		//wait for server response
		response = waitForCryptMessage();
		if(response == null) {
			return false;
		}
		
		try {
			//should be an Network settings message
			if(response.type != ShawWifiMessage.TYPE_NETWORKSETTINGS) throw new UnexpectedMessageException("expected network settings message");
			if(response.length != 1) throw new UnexpectedMessageException("expected 1 header");
			
			if(!response.header[0].equals("OK")) throw new UnexpectedMessageException("expected header OK " + response.header[0]);
			
			String resultStr = new String(response.data[0]);
			if(resultStr.equals("true")) {
				publishProgress("Updating network settings...");
				return true;
			} else {
				publishProgress("Server instructs to not update network settings..." + resultStr);
				return false;
			}
		} catch(UnexpectedMessageException e) {
			e.printStackTrace();
			publishProgress("Received unexpected message from server, please make sure you have the most recent version of the application");
			return false;
		}
	}
}
